home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Language/OS - Multiplatform Resource Library
/
LANGUAGE OS.iso
/
et
/
et3_0-a1.lha
/
et3
/
src
/
PRINTERS
/
PostScript.C
< prev
next >
Wrap
C/C++ Source or Header
|
1992-08-26
|
28KB
|
1,058 lines
#include "Object.h" // cpp max nesting level...
#include "Class.h"
#include "Error.h"
#include "CLib.h"
#include "System.h"
#include "String.h"
#include "DevBitmap.h"
#include "OrdColl.h"
#include "OneOfCluster.h"
#include "ManyOfCluster.h"
#include "Expander.h"
#include "BorderItems.h"
#include "Buttons.h"
#include "Env.h"
#include "Form.h"
#include "PopupItem.h"
#include "Menu.h"
#include "Fields.h"
#include "Math.h"
#include "Printer.h"
#include "PrintPort.h"
#include "PrintManager.h"
const int cIdName = cIdFirstUser + 1,
cIdOptions = cIdFirstUser + 10,
cIdResolution = cIdFirstUser + 20,
cIdOrientation= cIdFirstUser + 30,
cIdPaperFormat= cIdFirstUser + 40;
const int cFirstFontId = 1174711,
cFontMask = ~(eFaceUnderline|eFaceOutline|eFaceShadow);
char *PsTmp = "etprt",
*LpPath = "/usr/ucb/lpr -P%s",
*TmpPath = "/usr/tmp";
static struct PaperFormat {
char *name;
int width, height;
Point Size()
{ return Point(width, height); }
} paperFormats[] = {
"A4 Letter", 595, 842,
"B5 Letter", 421, 595,
"US Letter", 615, 750,
"US Legal", 615, 842,
"US Envelope Centered", 615, 300,
0
};
//---- PostScriptSettings ------------------------------------------------------------
class PostScriptSettings : public PrinterSettings {
public:
float resolution;
bool portrait;
bool smooth;
bool wysiwyg;
bool prolog;
char *prname;
public:
MetaDef(PostScriptSettings);
PostScriptSettings();
~PostScriptSettings();
OStream& PrintOn(OStream &s);
IStream& ReadFrom(IStream &s);
};
//---- PostScriptPort ----------------------------------------------------------
class PostScriptPort: public PrintPort {
friend class RFont;
PostScriptSettings *pst;
bool tofile;
float xorigin, yorigin;
FILE *pfp, *prfp;
int lastpsz, maxfont, bcnt, pagecnt, currpage;
char *PrintTmpFile;
Font *lbfont, *lfont;
byte bbuf[MaxTextBatchCnt];
class OrdCollection *ProcSets, *Fonts;
protected:
void SetPenSize(int pensize);
void EnrollFont(Font *fd);
void UseProcSet(char *name);
Rectangle *PrintBBox(Rectangle &bbox);
void downloadfont(FILE *ofp, Font *fd, char *fname);
public:
MetaDef(PostScriptPort);
PostScriptPort(char *name, PostScriptSettings *pst);
~PostScriptPort();
void DevOpenPage(int pn);
void DevClosePage();
void DevSetPattern(class DevBitmap*);
void DevSetOther(int);
void DevSetGrey(float f);
void DevSetColor(RGBColor *cp);
void DevClip(Rectangle);
void DevStrokeLine(int, Rectangle*, GrLineCap, Point, Point);
void DevStrokeRect(int, Rectangle*);
void DevFillRect(Rectangle*);
void DevStrokeOval(int, Rectangle*);
void DevFillOval(Rectangle*);
void DevStrokeRRect(int, Rectangle*, Point);
void DevFillRRect(Rectangle*, Point);
void DevStrokeWedge(int, GrLineCap, Rectangle*, int, int);
void DevFillWedge(Rectangle*, int, int);
void DevStrokePolygon(Rectangle*, Point*, int, GrPolyType t, int, GrLineCap);
void DevFillPolygon(Rectangle*, Point*, int, GrPolyType t);
void DevShowBitmap(Rectangle*, struct Bitmap*);
void DevShowChar(Font *fdp, Point pos, byte c, Rectangle*);
void DevShowTextBatch(Rectangle*, Point);
void DevGiveHint(int, int, void*);
bool DevScale(float sx, float sy);
};
//---- PostScriptPrinter -------------------------------------------------------
class PostScriptPrinter : public Printer {
OneOfCluster *orientation;
FloatField *resolution;
ManyOfCluster *options;
TextField *eti;
Menu *paperFormatMenu;
PopupButton *paperFormatPopup;
public:
MetaDef(PostScriptPrinter);
PostScriptPrinter()
{ }
char *GetName()
{ return "PostScript"; }
PrintPort *MakePrintPort(char *name)
{ return new PostScriptPort(name, (PostScriptSettings*) settings); }
bool CanSave()
{ return TRUE; }
bool CanPrint()
{ return TRUE; }
PrinterSettings *MakeSettings()
{ return new PostScriptSettings; }
VObject *DoCreatePrintDialog();
void LoadSettings(PrinterSettings*);
void StoreSettings(PrinterSettings*);
};
//---- FMap --------------------------------------------------------------------
static struct FMap {
char *name;
int encode;
GrFont fid;
GrFace face;
} fmap[] = {
"AvantGarde-Book", 1, eFontAvantgarde, eFacePlain,
"AvantGarde-BookOblique", 1, eFontAvantgarde, eFaceItalic,
"AvantGarde-Demi", 1, eFontAvantgarde, eFaceBold,
"AvantGarde-DemiOblique", 1, eFontAvantgarde, (GrFace)(eFaceItalic | eFaceBold),
"Bookman-Light", 1, eFontBookman, eFacePlain,
"Bookman-LightItalic", 1, eFontBookman, eFaceItalic,
"Bookman-Demi", 1, eFontBookman, eFaceBold,
"Bookman-DemiItalic", 1, eFontBookman, (GrFace)(eFaceItalic | eFaceBold),
"Courier", 1, eFontCourier, eFacePlain,
"Courier-Oblique", 1, eFontCourier, eFaceItalic,
"Courier-Bold", 1, eFontCourier, eFaceBold,
"Courier-BoldOblique", 1, eFontCourier, (GrFace)(eFaceItalic | eFaceBold),
"Helvetica", 1, eFontHelvetica, eFacePlain,
"Helvetica-Oblique", 1, eFontHelvetica, eFaceItalic,
"Helvetica-Bold", 1, eFontHelvetica, eFaceBold,
"Helvetica-BoldOblique", 1, eFontHelvetica, (GrFace)(eFaceItalic | eFaceBold),
"Helvetica-Narrow", 1, eFontNHelvetica, eFacePlain,
"Helvetica-Narrow-Oblique", 1, eFontNHelvetica, eFaceItalic,
"Helvetica-Narrow-Bold", 1, eFontNHelvetica, eFaceBold,
"Helvetica-Narrow-BoldOblique", 1, eFontNHelvetica, (GrFace)(eFaceItalic | eFaceBold),
"NewCenturySchlbk-Roman", 1, eFontSchoolbook, eFacePlain,
"NewCenturySchlbk-Italic", 1, eFontSchoolbook, eFaceItalic,
"NewCenturySchlbk-Bold", 1, eFontSchoolbook, eFaceBold,
"NewCenturySchlbk-BoldItalic", 1, eFontSchoolbook, (GrFace)(eFaceItalic | eFaceBold),
"Palatino-Roman", 1, eFontPalatino, eFacePlain,
"Palatino-Italic", 1, eFontPalatino, eFaceItalic,
"Palatino-Bold", 1, eFontPalatino, eFaceBold,
"Palatino-BoldItalic", 1, eFontPalatino, (GrFace)(eFaceItalic | eFaceBold),
"Symbol", 0, eFontSymbol, eFacePlain,
"Times-Roman", 1, eFontTimes, eFacePlain,
"Times-Italic", 1, eFontTimes, eFaceItalic,
"Times-Bold", 1, eFontTimes, eFaceBold,
"Times-BoldItalic", 1, eFontTimes, (GrFace)(eFaceItalic | eFaceBold),
"ZapfChancery-MediumItalic", 1, eFontChancery, eFacePlain,
"ZapfDingbats", 0, eFontDingbats, eFacePlain,
0
};
static FMap *FindFont(GrFont fid, GrFace face)
{
int i;
for (i= 0; fmap[i].name; i++)
if (fmap[i].fid == fid && fmap[i].face == face)
return &fmap[i];
return 0;
}
static char *MapName(GrFont fid, GrFace face)
{
FMap *fm= FindFont(fid, (GrFace)(face & cFontMask));
if (fm)
return fm->name;
return gFontManager->IdToName(fid);
}
static bool IsPSFont(GrFont fid)
{
FMap *fm= FindFont(fid, eFacePlain);
if (fm)
return TRUE;
return FALSE;
}
static bool Reencode(GrFont fid)
{
FMap *fm= FindFont(fid, eFacePlain);
if (fm)
return fm->encode;
return FALSE;
}
static char *EtName(GrFont fid, GrFace face)
{
return form("%s-%s", gFontManager->IdToName(fid),
gFontManager->StyleString((GrFace)(face & cFontMask)));
}
//---- output functions ---------------------------------------------------------
/*
%c PostScript character byte
%f floating point float
%d integer integer
%x 2-digit hex num byte
%r Rectangle Rectangle*
%p Point Point
%s 0-terminated string char*
*/
static void Printf(FILE *pfp, char *va_(format), ...)
{
static char *t= "0123456789abcdef";
register char c;
unsigned int b;
char *s;
Point *p;
int i;
double d;
Rectangle *r;
va_list ap;
va_start(ap,va_(format));
char *fmt= va_(format);
while (c= *fmt++) {
switch (c) {
case '%':
switch (c= *fmt++) {
case '%':
fputc('%', pfp);
break;
case 'c':
b= va_arg(ap, unsigned int);
if (b >= ' ' && b <= '~') {
if (b == '\\' || b == '(' || b == ')')
fputc('\\', pfp);
fputc(b, pfp);
} else
fprintf(pfp, "\\%03o", b);
break;
case 'f':
d= va_arg(ap, double);
fprintf(pfp, "%.3f", d);
break;
case 'd':
i= va_arg(ap, int);
fprintf(pfp, "%d", i);
break;
case 'x':
b= va_arg(ap, unsigned int);
fputc(t[(b&0xff)>>4], pfp);
fputc(t[b&0xf], pfp);
break;
case 's':
s= va_arg(ap, char*);
while (c= *s++)
fputc(c, pfp);
break;
case 'r':
r= va_arg(ap, Rectangle*);
fprintf(pfp, "%d %d %d %d", r->origin.x, r->origin.y, r->extent.x,
r->extent.y);
break;
case 'p':
p= va_arg(ap, Point*);
fprintf(pfp, "%d %d", (int) p->x, (int) p->y);
break;
default:
fputc(c, pfp);
break;
}
break;
default:
fputc(c, pfp);
break;
}
}
va_end(ap);
}
//---- PostScriptSettings ------------------------------------------------------------
NewMetaImpl(PostScriptSettings, PrinterSettings, (T(resolution), TB(portrait),
TB(smooth), TB(wysiwyg), TB(prolog), TS(prname)));
PostScriptSettings::PostScriptSettings()
: PrinterSettings(Point(595, 842), Point(50), Point(50), gRect0)
{
portrait= prolog= TRUE;
smooth= wysiwyg= FALSE;
resolution= 1.0;
prname= strsave(Env::GetValue("PRINTER", "lp"));
}
PostScriptSettings::~PostScriptSettings()
{
SafeDelete(prname);
}
OStream& PostScriptSettings::PrintOn (OStream &s)
{
PrinterSettings::PrintOn(s);
return s << portrait SP << prolog SP << smooth SP
<< wysiwyg SP << resolution SP << prname SP;
}
IStream& PostScriptSettings::ReadFrom(IStream &s)
{
char buf[100];
PrinterSettings::ReadFrom(s);
s >> portrait >> prolog >> smooth >> wysiwyg >> resolution >> buf;
SafeDelete(prname);
prname= strsave(buf);
return s;
}
//---- PSResource --------------------------------------------------------------
class PSResource : public Object {
static char *lasttag;
protected:
char *type, *name;
bool supplied;
public:
PSResource(char *t, bool suppl)
{ type= t; supplied= suppl; name= 0; }
~PSResource()
{ SafeDelete(name); }
char *GetName()
{ return name; }
void Load(FILE *ofp);
virtual void load(FILE *ofp) = 0;
void Do(FILE *ofp, char *t);
void Used(FILE *ofp)
{ Do(ofp, ""); }
void Supplied(FILE *ofp)
{ if (supplied) Do(ofp, "Supplied"); }
void Needed(FILE *ofp)
{ if (!supplied) Do(ofp, "Needed"); }
};
char *PSResource::lasttag;
void PSResource::Load(FILE *ofp)
{
if (supplied)
load(ofp);
else
Printf(ofp, "%%%%Include%s: %s\n", type, name);
}
void PSResource::Do(FILE *ofp, char *t)
{
if (lasttag == 0 || strcmp(lasttag, t) != 0) {
Printf(ofp, "%%%%Document%s%ss: %s\n", t, type, name);
lasttag= t;
} else
Printf(ofp, "%%%%+ %s\n", name);
}
//---- ProcSet -----------------------------------------------------------------
class ProcSet : public PSResource {
public:
ProcSet(char *n, bool pro) : PSResource("ProcSet", pro)
{ name= strsave(n); }
void load(FILE *ofp);
};
void ProcSet::load(FILE *ofp)
{
char buf[256];
for (int i= 0; name[i]; i++) {
if (name[i] == ' ')
buf[i]= '-';
else
buf[i]= name[i];
}
buf[i]= 0;
FILE *fin= fopen(form("%s/postscript/%s.ps", gEtDir, buf), "r");
if (fin) {
while (fgets(buf, sizeof(buf), fin))
fputs(buf, ofp);
fclose(fin);
} else
fprintf(stderr, "can't load procset <%s>\n", buf);
}
//---- RFont -------------------------------------------------------------------
class RFont : public PSResource {
PostScriptPort *psp;
public:
GrFont fid;
GrFace face;
public:
RFont(PostScriptPort *p, GrFont fd, GrFace fc);
void load(FILE *ofp)
{ psp->downloadfont(ofp, new_Font(fid, 12, face, TRUE), name); }
void SetUp(FILE *ofp);
};
RFont::RFont(PostScriptPort *p, GrFont fd, GrFace fc)
: PSResource("Font", !IsPSFont(fd))
{
psp= p;
fid= fd;
face= fc;
name= strsave(MapName(fd, fc));
}
void RFont::SetUp(FILE *ofp)
{
Printf(ofp, "/%s /%s findfont def\n", EtName(fid, face), name);
if (Reencode(fid))
Printf(ofp, "/%s Reencode\n", EtName(fid, face));
}
//---- PostScriptPort ----------------------------------------------------------
NewMetaImpl0(PostScriptPort, PrintPort);
PostScriptPort::PostScriptPort(char *name, PostScriptSettings *st) : PrintPort(name)
{
pst= st;
hascolor= TRUE;
ProcSets= new OrdCollection;
Fonts= new OrdCollection;
xorigin= 0.0;
yorigin= (pst->portrait) ? 842.0 : 0.0;
tofile= (name != 0);
pagecnt= 0;
UseProcSet("et 2.2 0");
if (tofile)
prfp= fopen(name, "w");
else
prfp= popen(form(LpPath, pst->prname), "w");
PrintTmpFile= tempnam((char*) TmpPath, (char*) PsTmp);
if (PrintTmpFile == NULL)
fprintf(stderr, "PostScriptPort::PostScriptPort: can't create tmpfile\n");
if ((pfp= fopen(PrintTmpFile, "w")) == NULL)
fprintf(stderr, "PostScriptPort::PostScriptPort: can't open tmpfile\n");
Printf(prfp, "%%!PS-Adobe-1.0\n");
Printf(prfp, "%%%%Title: title\n");
Printf(prfp, "%%%%Creator: ET++\n");
Printf(prfp, "%%%%CreationDate: date\n");
Printf(prfp, "%%%%For: User\n");
Printf(prfp, "%%%%DocumentData: Clean7Bit\n");
Printf(prfp, "%%%%LanguageLevel: 1\n");
Printf(prfp, "%%%%Orientation: %s\n", pst->portrait ? "Portrait"
: "Landscape");
Printf(prfp, "%%%%PageOrder: Ascend\n");
Printf(prfp, "%%%%Version: 2.2 1\n");
}
PostScriptPort::~PostScriptPort()
{
FlushMyText();
Printf(pfp, "%%%%Trailer\n");
Printf(pfp, "end\n");
Printf(pfp, "%%%%EOF\n");
fclose(pfp);
{ ProcSets->ForEach(ProcSet,Used)(prfp); }
{ ProcSets->ForEach(ProcSet,Supplied)(prfp); }
{ ProcSets->ForEach(ProcSet,Needed)(prfp); }
{ Fonts->ForEach(RFont,Used)(prfp); }
{ Fonts->ForEach(RFont,Supplied)(prfp); }
{ Fonts->ForEach(RFont,Needed)(prfp); }
Printf(prfp, "%%%%Pages: %d\n", pagecnt);
Printf(prfp, "%%%%BoundingBox: %r\n", PrintBBox(bbox));
Printf(prfp, "%%%%EndComments\n");
Printf(prfp, "%%%%BeginProlog\n");
{ ProcSets->ForEach(ProcSet,Load)(prfp); }
Printf(prfp, "%%%%EndProlog\n");
Printf(prfp, "%%%%BeginSetup\n");
Printf(prfp, "ET++Dict begin\n");
{ Fonts->ForEach(RFont,Load)(prfp); }
{ Fonts->ForEach(RFont,SetUp)(prfp); }
Printf(prfp, "%%%%EndSetup\n");
{
char buf[256];
register FILE *rpfp;
if ((rpfp= fopen(PrintTmpFile, "r")) == NULL) {
fprintf(stderr, "PostScriptPort::~PostScriptPort: can't open tmpfile %s\n", PrintTmpFile);
return;
}
while (fgets(buf, sizeof(buf), rpfp) != NULL)
fputs(buf, prfp);
fclose(rpfp);
CLib::Unlink(PrintTmpFile);
}
if (tofile)
fclose(prfp);
else
pclose(prfp);
if (ProcSets) {
ProcSets->FreeAll();
SafeDelete(ProcSets);
}
if (Fonts) {
Fonts->FreeAll();
SafeDelete(Fonts);
}
}
Rectangle *PostScriptPort::PrintBBox(Rectangle &bbox)
{
static Rectangle r;
r.origin.x= (int)(xorigin + pst->resolution*bbox.origin.x - 0.5),
r.origin.y= (int)(yorigin - pst->resolution*(bbox.origin.y + bbox.extent.y) - 0.5),
r.extent.x= (int)(xorigin + pst->resolution*(bbox.origin.x + bbox.extent.x) + 0.5),
r.extent.y= (int)(yorigin - pst->resolution*bbox.origin.y + 0.5);
return &r;
}
//---- Open, Close -------------------------------------------------------------
void PostScriptPort::DevOpenPage(int pn)
{
lastpsz= -1;
lbfont= 0;
currpage= pn;
Printf(pfp, "%%%%Page: %d %d\n", pagecnt+1, currpage);
Printf(pfp, "%%%%PageBoundingBox: (atend)\n");
Printf(pfp, "%%%%BeginPageSetup\n");
Printf(pfp, "save\n");
Printf(pfp, "%f %f %d %f init\n", xorigin, yorigin, pst->portrait ? 0 : 90,
pst->resolution);
Printf(pfp, "%%%%EndPageSetup\n");
}
void PostScriptPort::DevClosePage()
{
Printf(pfp, "Restore\n");
if (pagebbox.IsNotEmpty()) {
if (gDebug)
Printf(pfp, "%r StrokeBBox\n", PrintBBox(pagebbox));
Printf(pfp, "showpage\n");
pagecnt++;
}
Printf(pfp, "%%%%PageTrailer\n");
Printf(pfp, "%%%%PageBoundingBox: %r\n", PrintBBox(pagebbox));
}
//---- clipping ----------------------------------------------------------------
void PostScriptPort::DevClip(Rectangle r)
{
Printf(pfp, "%r SetClip\n", &r);
lastpsz= -1;
lbfont= 0;
}
bool PostScriptPort::DevScale(float sx, float sy)
{
Printf(pfp, "%f %f scale\n", sx, sy);
return TRUE;
}
//---- color -------------------------------------------------------------------
void PostScriptPort::DevSetGrey(float f)
{
Printf(pfp, "%f SetGray\n", f);
}
void PostScriptPort::DevSetColor(RGBColor *cp)
{
Printf(pfp, "%f %f %f setrgbcolor\n", cp->GetRed() / 255.0,
cp->GetGreen() / 255.0,
cp->GetBlue() / 255.0);
//DevSetGrey(cp->AsGreyLevel() / 255.0);
cp->SetId(-1);
}
void PostScriptPort::DevSetPattern(DevBitmap *bmp)
{
Printf(pfp, "<");
for (int y= 0; y < bmp->Size().y; y++)
Printf(pfp, "%x", bmp->GetByte(0, y));
Printf(pfp, "> SetPattern\n");
}
void PostScriptPort::DevSetOther(int pid)
{
Printf(pfp, "%f SetGray\n", pid == 1 ? 1.0 : 0.0);
}
void PostScriptPort::SetPenSize(int pensize)
{
if (pensize < 0 || (pensize == lastpsz))
return;
lastpsz= pensize;
Printf(pfp, "%d SetPenSize\n", pensize);
}
//---- drawing -----------------------------------------------------------------
void PostScriptPort::DevStrokeLine(int pensize, Rectangle *r,
GrLineCap cap, Point p1, Point p2)
{
SetPenSize(pensize);
Merge(r);
Printf(pfp, "%p %p %d StrokeArrow\n", &p1, &p2, cap);
}
void PostScriptPort::DevStrokeRect(int psz, Rectangle *r)
{
Merge(r);
SetPenSize(psz);
Printf(pfp, "%r StrokeRect\n", r);
}
void PostScriptPort::DevFillRect(Rectangle *r)
{
Merge(r);
Printf(pfp, "%r FillRect\n", r);
}
void PostScriptPort::DevStrokeOval(int psz, Rectangle *r)
{
Merge(r);
SetPenSize(psz);
Printf(pfp, "%r StrokeOval\n", r);
}
void PostScriptPort::DevFillOval(Rectangle *r)
{
Merge(r);
Printf(pfp, "%r FillOval\n", r);
}
void PostScriptPort::DevStrokeRRect(int psz, Rectangle *r, Point dia)
{
Merge(r);
SetPenSize(psz);
Printf(pfp, "%r %p StrokeRoundRect\n", r, &dia);
}
void PostScriptPort::DevFillRRect(Rectangle *r, Point dia)
{
Merge(r);
Printf(pfp, "%r %p FillRoundRect\n", r, &dia);
}
void PostScriptPort::DevStrokeWedge(int psz, GrLineCap, Rectangle *r, int s, int d)
{
Point e(s, d);
Merge(r);
SetPenSize(psz);
Printf(pfp, "%r %p StrokeWedge\n", r, &e);
}
void PostScriptPort::DevFillWedge(Rectangle *r, int s, int d)
{
Point e(s, d);
Merge(r);
Printf(pfp, "%r %p FillWedge\n", r, &e);
}
void PostScriptPort::DevStrokePolygon(Rectangle *r, Point *pts,
int npts, GrPolyType t, int psz, GrLineCap)
{
Merge(r);
SetPenSize(psz);
Printf(pfp, "%r %d %d %p [\n", r, (pts[0] == pts[npts-1]) ? 1 : 0,
(t & ePolyBezier) ? 1 : 0, &r->extent);
for (int i= 0; i < npts; i++)
Printf(pfp, "%p ", &pts[i]);
Printf(pfp, "\n] StrokePoly\n");
}
void PostScriptPort::DevFillPolygon(Rectangle *r, Point *pts, int npts,
GrPolyType t)
{
Merge(r);
Printf(pfp, "%r %d %d %p [\n", r, (pts[0] == pts[npts-1]) ? 1 : 0,
(t & ePolyBezier) ? 1 : 0, &r->extent);
for (int i= 0; i < npts; i++)
Printf(pfp, "%p ", &pts[i]);
Printf(pfp, "\n] FillPoly\n");
}
//---- text batching -----------------------------------------------------------
void PostScriptPort::DevShowChar(Font *fdp, Point delta, byte c, Rectangle*)
{
if (fdp != lfont || delta != gPoint0)
FlushAnyText();
if (bcnt == 0) // first
lfont= fdp;
bbuf[bcnt++]= c;
}
void PostScriptPort::DevShowTextBatch(Rectangle *r, Point pos)
{
int i, w= 0;
register byte c;
Merge(r);
if (lbfont != lfont) {
EnrollFont(lfont);
Printf(pfp, "%s %d scalesetfont\n",
EtName(lfont->Fid(), lfont->Face()), lfont->Size());
lbfont= lfont;
}
if (bcnt > 0) {
Printf(pfp, "%p m(", &pos);
for (i= 0; i < bcnt; i++) {
c= bbuf[i];
w+= lfont->Width(c);
Printf(pfp, "%c", c);
}
if (bcnt > 1)
Printf(pfp, ") %d sshow\n", w);
else
Printf(pfp, ") show\n");
bcnt= 0;
}
}
//---- bitmaps & images --------------------------------------------------------
void PostScriptPort::DevShowBitmap(Rectangle *r, Bitmap *bm)
{
int bytes, x, y, by, lines, yy;
Point e= bm->Size();
DevBitmap *bmp= bm->GetDevBitmap();
Merge(r);
if (!gDebug && pst->smooth) {
bytes= bm->ShortsPerLine() * 2;
lines= 1250 / bytes;
UseProcSet("smooth 2.2 0");
Printf(pfp, "%d %d div %d %d div %p %d %d SmoothBitmapStart\n",
r->extent.x, e.x, r->extent.y, e.y, &r->origin, bytes, e.x);
for (by= 0, y= 0; y < e.y; y+= by) {
by= Math::Min(lines, e.y-y);
Printf(pfp, "%d Band\n", by);
for(yy= y-2; yy < y+by+2; yy++) {
for (x= 0; x < bytes; x++)
Printf(pfp, "%x", bmp->GetByte(x, yy));
Printf(pfp, "\n");
}
}
Printf(pfp, "SmoothBitmapEnd\n");
} else {
Printf(pfp, "%r %p %d Bitmap\n", r, &e, bmp->Depth());
if (bmp->Depth() == 1) {
bytes= bmp->BytesPerLine(); // postscript images are Byte aligned
for (y= 0; y < e.y; y++) {
for (x= 0; x < bytes; x++)
Printf(pfp, "%x", bmp->GetByte(x, y));
Printf(pfp, "\n");
}
} else {
bytes= bmp->BytesPerLine(); /* postscript images are Byte aligned */
int cmssize= bmp->GetColormapSize();
int *grey= new int[cmssize];
for (int i= 0; i < cmssize; i++)
grey[i]= bmp->GetColormapEntry(i).AsGreyLevel();
for (y= 0; y < e.y; y++) {
for (x= 0; x < bytes; x++)
Printf(pfp, "%x", grey[bmp->GetPixel(x, y)]);
Printf(pfp, "\n");
}
delete grey;
}
}
}
//---- hints -------------------------------------------------------------------
void PostScriptPort::DevGiveHint(int code, int, void *vp)
{
char buf[300];
switch (code) {
case 55:
Printf(pfp, "%d %d translate\n", origin.x, origin.y);
break;
case 55559:
if (sscanf((char*)vp, "%s", buf) == 1) {
FILE *fp;
if (fp= fopen(buf, "r")) {
while (fgets(buf, 299, fp))
if (buf[0] != '%')
fputs(buf, pfp);
fclose(fp);
}
}
break;
case eHintPostScript:
Printf(pfp, "%s", (char*) vp);
break;
case eHintEPSFStart:
Printf(pfp, "BeginEPSF\n");
ignore= TRUE;
break;
case eHintEPSFEnd:
Printf(pfp, "EndEPSF\n");
ignore= FALSE;
break;
case 66666:
byte *dash= (byte*) vp;
Printf(pfp, "[");
for (int i= 0; i < dash[2]; i++)
Printf(pfp, " %d", dash[i+3]);
Printf(pfp, "] %d setdash\n", dash[0]);
break;
case 66667:
Printf(pfp, "%s", "[] 0 setdash\n");
break;
case 77777: // RotateBegin
Printf(pfp, "%s", (char*) vp);
break;
case 77778: // RotateBegin
Printf(pfp, "%s", (char*) vp);
break;
}
}
//---- misc functions ---------------------------------------------------------
void PostScriptPort::EnrollFont(Font *fd)
{
Iter next(Fonts);
register RFont *rf;
while (rf= (RFont*) next())
if (fd->Fid() == rf->fid && fd->Face() == rf->face)
return;
Fonts->Add(new RFont(this, fd->Fid(), fd->Face()));
}
void PostScriptPort::UseProcSet(char *name)
{
Iter next(ProcSets);
register ProcSet *ps;
while (ps= (ProcSet*) next())
if (strcmp(name, ps->GetName()) == 0)
return;
ProcSets->Add(new ProcSet(name, pst->prolog));
}
void PostScriptPort::downloadfont(FILE *ofp, Font *fd, char *fname)
{
int z, i, x, y, ps, llx, lly, urx, ury, bytesperline;
DevBitmap *dbm;
Point offset, size;
llx= lly= 9999;
urx= ury= 0;
ps= fd->Size();
Printf(ofp, "%%%%BeginFont: %s\n", fname);
Printf(ofp, "/%s %d %d [\n", fname, cFirstFontId+fd->Fid()*256+fd->Face(), ps);
for (z= i= 0; i < cCharsPerFont; i++) {
if ((dbm= fd->CharAsBitmap(i, &offset)) == 0)
continue;
dbm->Ref();
size= dbm->Size();
llx= Math::Min(llx, offset.x);
lly= Math::Min(lly, offset.y);
urx= Math::Max(urx, offset.x+size.x);
ury= Math::Max(ury, offset.y+size.y);
Printf(ofp, "<%x%x%x%x%x%x", i, fd->Width(i), size.x, size.y, offset.x,
offset.y-size.y);
if (pst->smooth) {
UseProcSet("smooth 2.2 0");
bytesperline= (((size.x+2)-1)/16+1)*2;
for (y= -2; y < size.y+2; y++) {
for (x= 0; x < bytesperline; x++)
Printf(ofp, "%x", dbm->GetByte(x, y));
}
} else {
bytesperline= (size.x-1) / 8 + 1;
for (y= 0; y < size.y; y++)
for (x= 0; x < bytesperline; x++)
Printf(ofp, "%x", dbm->GetByte(x, y));
}
Printf(ofp, ">\n");
z++;
dbm->Unref();
}
Printf(ofp, "] %d %d %d %d %d new%sbitmapfont\n", z, llx, lly, urx, ury,
pst->smooth ? "smoothed" : "");
Printf(ofp, "%%%%EndFont\n");
}
//---- PostScriptPrinter -------------------------------------------------------
NewMetaImpl(PostScriptPrinter, Printer, (TP(orientation), TP(resolution), TP(options), TP(eti)));
void PostScriptPrinter::LoadSettings(PrinterSettings *ps)
{
if (eti) {
PostScriptSettings *settings= (PostScriptSettings*) ps;
options->SetItem(cIdOptions+0, settings->smooth);
options->SetItem(cIdOptions+1, settings->wysiwyg);
options->SetItem(cIdOptions+2, settings->prolog);
resolution->SetValue(settings->resolution*100.0);
orientation->SetItemOn(cIdOrientation + (settings->portrait ? 0 : 1));
eti->SetString(settings->prname);
Point pap= settings->paperSize;
if (!settings->portrait)
pap= Flip(pap);
for (int i= 0; paperFormats[i].name; i++)
if (paperFormats[i].Size() == pap)
break;
if (paperFormats[i].name == 0)
paperFormatMenu->AppendItem(form("%d x %d points", pap.x, pap.y), i);
paperFormatPopup->SetValue(i);
}
}
void PostScriptPrinter::StoreSettings(PrinterSettings *ps)
{
PostScriptSettings *settings= (PostScriptSettings*) ps;
settings->smooth= options->IsItemOn(cIdOptions+0);
settings->wysiwyg= options->IsItemOn(cIdOptions+1);
settings->prolog= options->IsItemOn(cIdOptions+2);
settings->resolution= resolution->GetValue()/100.0;
int si= paperFormatPopup->GetValue();
int maxsize= (sizeof(paperFormats)/sizeof(PaperFormat))-1;
if (si >= 0 && si < maxsize)
settings->SetPaperSize(paperFormats[si].Size());
paperFormatMenu->RemoveItem(maxsize);
settings->portrait= orientation->GetCurrentItem() == cIdOrientation;
if (!settings->portrait)
settings->SetPaperSize(Flip(settings->GetPaperSize()));
SafeDelete(settings->prname);
settings->prname= strsave(eti->AsString());
}
VObject *PostScriptPrinter::DoCreatePrintDialog()
{
orientation=
new OneOfCluster(cIdOrientation, eVObjHLeft, 5,
"Portrait",
"Landscape",
0
);
options=
new ManyOfCluster(cIdOptions, eVObjHLeft, 5,
"Smooth Bitmaps",
"Smooth Text",
"Include ProcSets",
0
);
paperFormatMenu= new Menu("Paper Formats", FALSE);
for (int i= 0; paperFormats[i].name; i++)
paperFormatMenu->AppendItem(paperFormats[i].name, i);
//---- overall layout ----
return
new VExpander(10,
new HBox(10, eVObjVTop,
new BorderItem("Options", options),
new BorderItem("Orientation", orientation),
0
),
new Form(cIdNone, eVObjHCenter, 2,
"Paper:", paperFormatPopup= new PopupButton(cIdPaperFormat,
0, paperFormatMenu),
"Scale:", resolution= new FloatField(cIdResolution, 100.0, 400.0, "%g %%"),
"Printer Name:", eti= new TextField(cIdName, 10),
0
),
0
);
}